﻿using System;
using System.ComponentModel;
using System.Windows.Data;

namespace Dsl.Ped.Common.Converters
{
    /// <summary>
    /// Converter which converts a value to a defined typ
    /// Used for binding against objects
    /// </summary>
    public class ChangeTypeConverter : IValueConverter
    {
        /// <summary>
        /// Gets or sets the type of the source property
        /// if value is set to null the default type will be used
        /// </summary>
        public Type SourceType { get; set; }

        /// <summary>
        /// Gets or sets the type of the target property
        /// if value is set to null the default type will be used
        /// </summary>
        public Type TargetType { get; set; }

        #region Implementation of IValueConverter

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value == null) return null;
            if (value is string && string.IsNullOrEmpty((string)value)) return null;

            var convertType = TargetType ?? targetType;

            if (value.GetType() == convertType) return value;
            if (convertType == typeof(object)) return value;

            try
            {
                if (convertType.IsEnum)
                {
                    if (value is string)
                    {
                        return Enum.Parse(convertType, value as string);
                    }

                    return Enum.ToObject(convertType, value);
                }

                // obtain the converter for the target type
                var converter = TypeDescriptor.GetConverter(convertType);
                
                // determine if the supplied value is of a suitable type
                return converter.ConvertFrom(converter.CanConvertFrom(value.GetType()) ? value : value.ToString());
            }
            catch (Exception)
            {
                return null;
            } 
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value == null) return null;
            if (value is string && string.IsNullOrEmpty((string)value)) return null;

            var convertType = SourceType ?? targetType;

            if (value.GetType() == convertType) return value;
            
            try
            {
                if (convertType.IsEnum)
                {
                    if (value is string)
                    {
                        return Enum.Parse(convertType, value as string);
                    }

                    return Enum.ToObject(convertType, value);
                }

                // obtain the converter for the target type
                var converter = TypeDescriptor.GetConverter(convertType);

                // determine if the supplied value is of a suitable type
                return converter.ConvertFrom(converter.CanConvertFrom(value.GetType()) ? value : value.ToString());
            } 
            catch (Exception)
            {
                return null;
            }
        }

        #endregion
    }
}